package cn.xiaopengstack.domain.activity.service.quota.rule.factory;

import cn.xiaopengstack.domain.activity.service.quota.rule.chain.IActionChain;
import cn.xiaopengstack.types.enums.ResponseCode;
import cn.xiaopengstack.types.exception.AppException;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiangyangang
 */
@Component
@Slf4j
public class DefaultActivityActionChainFactory {

    private final List<IActionChain> actionChain;
    private final List<ActionEnum> actionEnumList;

    public DefaultActivityActionChainFactory(List<IActionChain> chains) {
        actionChain = chains;
        actionEnumList = chains.stream().map(IActionChain::action).collect(Collectors.toList());
    }


    /**
     * 构造一些基础的检查
     * 有效性
     * 库存
     * @return
     */
    public IActionChain buildBaseChain(){
        return buildYourChain(ActionEnum.VALIDITY_CHECK_ACTION, ActionEnum.STOCK_CHECK_ACTION);
    }

    /**
     * 构造一些基础的检查
     * 有效性
     * 库存
     * @return
     */
    public IActionChain buildCreateOrderChain(){
        return buildYourChain(ActionEnum.VALIDITY_CHECK_ACTION, ActionEnum.STOCK_CHECK_ACTION, ActionEnum.DECR_STOCK);
    }

    /**
     * 自定义构造责任链
     * @param actionList
     * @return
     */
    public IActionChain buildYourChain(ActionEnum... actionList){

        // 追加一个默认的兜底链
        List<ActionEnum> actions = new ArrayList<>(Arrays.asList(actionList));

        // 做一个存在性检查
        Optional<ActionEnum> anyNotMatchAction = actions.stream().filter((action) -> !actionEnumList.contains(action)).findAny();
        if (anyNotMatchAction.isPresent()) {
            throw new AppException(ResponseCode.UNKNOWN_ACTIVITY_ACTION.getCode(), String.format(ResponseCode.UNKNOWN_ACTIVITY_ACTION.getInfo(), anyNotMatchAction.get().getAction()));
        }

        // 组装
        List<IActionChain> selectChains = actionChain.stream()
                .filter((chain) -> actions.contains(chain.action()))
                .sorted(Comparator.comparing(IActionChain::getOrder))
                .collect(Collectors.toList());

        IActionChain firstChain = selectChains.get(0);

        return selectChains.stream()
                .skip(1)
                .reduce(firstChain, IActionChain::appendChain);
    }

    @Getter
    @AllArgsConstructor
    public enum ActionEnum{
        VALIDITY_CHECK_ACTION("validity_check_action", "有效性检查", 1),
        STOCK_CHECK_ACTION("stock_check_action", "库存检查", 2),
        DECR_STOCK("decr_stock", "库存扣减", 3),
        DEFAULT("default", "兜底检查", Integer.MAX_VALUE);
        private final String action;
        private final String desc;
        private final Integer order;


    }
}
